package com.jiangli.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.esotericsoftware.minlog.Log;
import com.jiangli.dto.IngredientDTO;
import com.jiangli.dto.IngredientPageQueryDTO;
import com.jiangli.entity.Dish;
import com.jiangli.entity.Ingredient;
import com.jiangli.entity.Merchant;
import com.jiangli.exception.BaseException;
import com.jiangli.mapper.IngredientMapper;
import com.jiangli.result.PageResult;
import com.jiangli.service.AdminIngredientService;
import com.jiangli.service.Search.Impl.IngredientIndexServiceImpl;
import com.jiangli.vo.DishBriefVO;
import com.jiangli.vo.IngredientVO;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.text.Collator;
import java.util.Locale;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.List;
import java.util.stream.Collectors;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
@Service
@Slf4j
public class AdminIngredientServiceImpl implements AdminIngredientService {
    private final IngredientServiceImpl ingredientService;
    private final IngredientMapper ingredientMapper;
    private final IngredientIndexServiceImpl ingredientIndexService;
    private final StringRedisTemplate redisTemplate;
    private final DishServiceImpl dishServiceImpl;
    private final MerchantServiceImpl merchantServiceImpl;


    private static final String DISH_INGREDIENT_DETAIL_PREFIX = "ingredient:detail:";
    private static final String DISH_INGREDIENT_PREFIX = "dish:ingredientIds:";
    private static final String INGREDIENT_DISH_ID_PREFIX = "ingredient:dishIdsConnection:";


    @Autowired
    public AdminIngredientServiceImpl(IngredientServiceImpl ingredientService,
                                      IngredientMapper ingredientMapper,
                                      IngredientIndexServiceImpl ingredientIndexService,
                                      StringRedisTemplate redisTemplate, DishServiceImpl dishServiceImpl,
                                      MerchantServiceImpl merchantServiceImpl) {
        this.ingredientService = ingredientService;
        this.ingredientMapper = ingredientMapper;
        this.ingredientIndexService = ingredientIndexService;
        this.redisTemplate = redisTemplate;
        this.dishServiceImpl = dishServiceImpl;
        this.merchantServiceImpl = merchantServiceImpl;
    }


    @Override
    public PageResult getIngredientByPage(IngredientPageQueryDTO ingredientPageQueryDTO) {
        List<Ingredient> ingredientList = ingredientService.getAllIngredientWithCache();
        String queryName = ingredientPageQueryDTO.getName();

        // 打印排序前的顺序
        Log.info("排序前的ID顺序: {}", ingredientList.stream().map(Ingredient::getId).toList().toString());

        // 正确的中文拼音比较器
        Comparator<Ingredient> chineseComparator = (o1, o2) -> {
            String name1 = o1.getName() != null ? o1.getName().trim() : "";
            String name2 = o2.getName() != null ? o2.getName().trim() : "";

            String firstPinyin1 = extractFirstPinyin(name1);
            String firstPinyin2 = extractFirstPinyin(name2);

            // 先比较首字母
            int result = firstPinyin1.compareTo(firstPinyin2);
            if (result != 0) {
                return result;
            }

            // 首字母相同则比较全名拼音
            return getFullPinyin(name1).compareTo(getFullPinyin(name2));
        };

        // 执行过滤和排序
        List<Ingredient> sortedIngredients = ingredientList.stream()
                .filter(ingredient -> {
                    if (queryName != null && !queryName.isEmpty()) {
                        return ingredient.getName() != null &&
                                ingredient.getName().contains(queryName);
                    }
                    return true;
                })
                .sorted(chineseComparator)
                .collect(Collectors.toList());

        // 打印排序后的结果
        Log.info("排序后的ID顺序: {}", sortedIngredients.stream().map(Ingredient::getId).toList().toString());

        // 提取ID并分页
        List<Long> sortedIds = sortedIngredients.stream()
                .map(Ingredient::getId)
                .toList();

        List<Ingredient> finallyIngredients = getIngredientResultByPage(
                sortedIds,
                ingredientPageQueryDTO.getPage(),
                ingredientPageQueryDTO.getPageSize()
        );

        // 确保分页结果也按相同规则排序
        finallyIngredients.sort(chineseComparator);

        PageResult pageResult = new PageResult();
        pageResult.setTotal(sortedIngredients.size()); // 注意：总数应为过滤后的数量
        pageResult.setRecords(finallyIngredients);
        return pageResult;
    }
    private String getFullPinyin(String name) {
        if (name == null || name.isEmpty()) {
            return "";
        }

        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);

        StringBuilder pinyin = new StringBuilder();
        for (char c : name.toCharArray()) {
            if (Character.toString(c).matches("[\\u4E00-\\u9FA5]")) {
                try {
                    String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c, format);
                    if (pinyinArray != null && pinyinArray.length > 0) {
                        pinyin.append(pinyinArray[0]);
                    }
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    Log.error("全拼转换失败", e);
                    pinyin.append(c);
                }
            } else {
                pinyin.append(c);
            }
        }
        return pinyin.toString();
    }
    private String extractFirstPinyin(String name) {
        if (name == null || name.isEmpty()) {
            return "";
        }

        char firstChar = name.charAt(0);
        // 处理空格等特殊字符
        if (Character.isWhitespace(firstChar)) {
            return " ";
        }

        // 非汉字直接返回首字符
        if (!Character.toString(firstChar).matches("[\\u4E00-\\u9FA5]")) {
            return String.valueOf(firstChar).toUpperCase();
        }

        // 汉字转拼音首字母
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        format.setCaseType(HanyuPinyinCaseType.UPPERCASE); // 大写
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); // 无音调

        try {
            String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(firstChar, format);
            if (pinyinArray != null && pinyinArray.length > 0) {
                return String.valueOf(pinyinArray[0].charAt(0)); // 返回首字母
            }
        } catch (BadHanyuPinyinOutputFormatCombination e) {
            Log.error("拼音转换失败", e);
        }

        return String.valueOf(firstChar).toUpperCase();
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addIngredient(IngredientDTO ingredientDTO) {
        Ingredient ingredient = new Ingredient();
        BeanUtils.copyProperties(ingredientDTO, ingredient);
      int count=  ingredientMapper.selectByName(ingredient.getName());
      if(count>0){
          throw new BaseException("食材已经存在");
      }
        try {
            ingredientMapper.addIngredient(ingredient);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BaseException("插入食材失败！");
        }
        //重建索引
        try {
            ingredientIndexService.buildDishIndex(ingredient);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BaseException("更新索引失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateIngredient(IngredientDTO ingredientDTO) {
        try {
            // 1. 校验入参是否为空
            if (ingredientDTO == null) {
                throw new IllegalArgumentException(" ingredientDTO 不能为null");
            }

            // 2. 校验关键参数id是否为空
            if (ingredientDTO.getId() == null) {
                throw new IllegalArgumentException(" ingredientDTO.id 不能为null");
            }

            Ingredient ingredient = new Ingredient();
            BeanUtils.copyProperties(ingredientDTO, ingredient);

            // 3. 再次校验转换后的对象及关键属性
            if (ingredient.getId() == null) {
                throw new IllegalArgumentException("ingredient.id 不能为null");
            }

            log.info("ingredient:{},{}", ingredient.getId(), ingredient.getName());

            // 删除索引（使用id）
            ingredientIndexService.deleteIngredientIndex(ingredient.getId());

            // 重建索引（使用完整对象）
            if (StringUtils.isEmpty(ingredient.getName())) {
                throw new IllegalArgumentException("ingredient.name 不能为null或空");
            }
            ingredientIndexService.buildDishIndex(ingredient);

            // 删除详情缓存（使用id）
            redisTemplate.delete(DISH_INGREDIENT_DETAIL_PREFIX + ingredient.getId());

            // 获取关联的菜品ID列表
            List<Long> dishIds = ingredientService.getDishIdsByIngredientIds(Collections.singletonList(ingredient.getId()));

            // 4. 校验集合及集合元素
            if (dishIds != null) {
                for (Long dishId : dishIds) {
                    if (dishId == null) {
                        throw new IllegalArgumentException("dishIds中包含null值");
                    }
                    String redisKey = DISH_INGREDIENT_PREFIX + dishId;
                    redisTemplate.delete(redisKey);
                }
            }

            // 删除关系缓存（使用id）
            redisTemplate.delete(INGREDIENT_DISH_ID_PREFIX + ingredient.getId());

            // 更新数据库（确保有必要的属性）
            ingredientMapper.updateIngredient(ingredient);
        } catch (Exception e) {
            log.error("更新食材失败: {}", e.getMessage(), e); // 建议打印完整堆栈
            throw e;
        }
    }

    @Override
    public IngredientVO getIngredientDetail(Long id) {
        Ingredient ingredient = ingredientMapper.getIngredientWithId(id);
        IngredientVO ingredientVO = new IngredientVO();
        BeanUtils.copyProperties(ingredient, ingredientVO);
        List<Long> dishIds = ingredientService.getDishIdsByIngredientIds(Collections.singletonList(ingredient.getId()));
        List<Dish> dishList = dishServiceImpl.getDishesFromCacheOrDB(dishIds);
        List<DishBriefVO> dishBriefVOListList = new ArrayList<>();
        for (Dish value : dishList) {
            DishBriefVO dishVO = new DishBriefVO();
            List<Long> merchantIds = new ArrayList<>();
            merchantIds.add((Long.valueOf(value.getMerchantId())));
            List<Merchant> merchant = merchantServiceImpl.getCurrentMerchant(merchantIds);
            log.info("商家应该有一个{}", merchant.size());
            merchant.add(new Merchant());
            BeanUtils.copyProperties(value, dishVO);
            log.info("商家{}", merchant.get(0));
            dishVO.setMerchant(merchant.get(0).getMerchantName());
            dishVO.setLocation(merchant.get(0).getLocation());
            dishBriefVOListList.add(dishVO);

        }
        ingredientVO.setDishBriefs(dishBriefVOListList);
        return ingredientVO;
    }


    /**
     * 分页获取材料
     * @param allIds 所有的ids
     * @param page 第几页
     * @param size 页数大小
     * @return 返回的材料
     */
    private List<Ingredient> getIngredientResultByPage(List<Long> allIds,int page,int size) {
        // 计算分页范围
        int start = (page - 1) * size;
        if (start < 0) start = 0;
        int end = Math.min(start + size, allIds.size());

        // 如果没有数据，返回空列表
        if (start >= end) {
            return Collections.emptyList();
        }

        // 获取当前页的ID列表
        List<Long> pageIds = new ArrayList<>(allIds.subList(start, end));
        return ingredientMapper.getIngredientsByIds(pageIds);

    }
}
